module adder_subtracter(
    input [3:0] A,  // 第一个4位二进制数
    input [3:0] B,  // 第二个4位二进制数
    input        sub, // 1表示减法，0表示加法
    output [3:0] sum, // 结果
    output       overflow // 溢出标志
);

// 进行加法或减法运算
wire [4:0] int_sum; // 使用5位宽的线来存储中间和，以检测溢出
assign int_sum = sub ? A + (~B + 1'b1) : A + B;

// 检查溢出
assign overflow = int_sum[4] != int_sum[3]; // 如果最高两位不相同，则溢出

// 计算结果的补码
wire [3:0] twos_complement_sum = ~int_sum[3:0] + 1'b1;

// 判断结果是否为负数，如果是，则进行补码到原码的转换
assign sum = int_sum[4] == 0 ? int_sum[3:0] : twos_complement_sum;

endmodule


`timescale 1ns / 1ps

module adder_subtracter_tb;

// 定义输入和输出信号
reg [3:0] A, B;
reg sub;
wire [3:0] sum;
wire overflow;

// 实例化被测试模块
adder_subtracter uut (
    .A(A), 
    .B(B), 
    .sub(sub), 
    .sum(sum), 
    .overflow(overflow)
);

// 初始化过程
initial begin
    // 初始化输入
    A = 0;
    B = 0;
    sub = 0;
    
    // 测试加法
    A = 4'b0111; // +7
    B = 4'b0001; // +1
    sub = 0;
    #10;
    
    // 测试减法
    A = 4'b0111; // +7
    B = 4'b0001; // +1
    sub = 1;
    #10;
    
    // 测试最大值加1导致溢出
    A = 4'b0111; // +7
    B = 4'b0001; // +1
    sub = 0;
    #10;
    
    // 测试最小值减1导致溢出
    A = 4'b1000; // -8
    B = 4'b0001; // +1
    sub = 1;
    #10;
    
    // 测试两个负数相加
    A = 4'b1000; // -8
    B = 4'b1010; // -6
    sub = 0;
    #10;
    
    // 测试两个正数相减
    A = 4'b0110; // +6
    B = 4'b0010; // +2
    sub = 1;
    #10;
    
    // 测试两个负数相减
    A = 4'b1000; // -8
    B = 4'b1010; // -6
    sub = 1;
    #10;
    
    // 测试正负数相加
    A = 4'b0110; // +6
    B = 4'b1000; // -8
    sub = 0;
    #10;
    
    // 测试正负数相减
    A = 4'b0110; // +6
    B = 4'b1000; // -8
    sub = 1;
    #10;
    
    // 测试零与任何数相加
    A = 4'b0000; // 0
    B = 4'b0111; // +7
    sub = 0;
    #10;
    
    // 测试零与任何数相减
    A = 4'b0000; // 0
    B = 4'b0111; // +7
    sub = 1;
    #10;
    
    // 测试两个相同的数相加
    A = 4'b0101; // +5
    B = 4'b0101; // +5
    sub = 0;
    #10;
    
    // 测试两个相同的数相减
    A = 4'b0101; // +5
    B = 4'b0101; // +5
    sub = 1;
    #10;
    
    // 测试所有位都是1的加法（潜在溢出）
    A = 4'b1111; // -1
    B = 4'b1111; // -1
    sub = 0;
    #10;
    
    // 测试所有位都是1的减法（潜在溢出）
    A = 4'b1111; // -1
    B = 4'b1111; // -1
    sub = 1;
    #10;
    
    // 结束仿真
    $finish;
end


endmodule